/**
 * Copyright (C), 2023-2033
 */
package com.goaly.gpt;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.PathUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.SystemPropsUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.goaly.gpt.consts.GptConstant;
import com.goaly.gpt.model.XfsGptMessage;
import com.goaly.gpt.model.XfsGptRequest;
import com.goaly.gpt.model.XfsGptResponse;
import groovy.lang.Tuple2;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jetbrains.annotations.NotNull;

/**
 * XfsTestCodeGenerator
 *
 * @author: lys
 * @date: 2023/6/26 13:38
 */
public class XfsTestCodeGenerator implements TestCodeGenerator {

    private String apiUrl = "http://192.168.2.105:7077/chatgpt/api/v1//chat/completions";

    private String apiKey;

    /**
     * 测试代码生成中标记
     */
    private final static AtomicBoolean TEST_CODE_GENERATING = new AtomicBoolean(false);

    public XfsTestCodeGenerator(String apiKey) {
        this.apiKey = apiKey;
    }

    public String getApiUrl() {
        String userHome = SystemPropsUtil.get(GptConstant.USER_HOME, true);
        String pathXfsChatGptApiUrl = StrUtil.format("{}/{}", userHome, GptConstant.PATH_XFS_CHAT_GPT_API_URL);
        if (PathUtil.exists(Paths.get(pathXfsChatGptApiUrl), false)) {
            apiUrl = FileUtil.readUtf8String(pathXfsChatGptApiUrl);
        }
        return apiUrl;
    }

    @Override
    public Tuple2<String, String> getCode(String className, String methodText) {
        if (TEST_CODE_GENERATING.get()) {
            throw new IllegalStateException("正在生成单元测试代码，请稍后再试。");
        }
        String testCode = StrUtil.EMPTY, resultText;
        if (StrUtil.isBlank(methodText)) {
            return new Tuple2<>(testCode, "方法体为空");
        }
        try {
            String simpleClassContent = getSimpleClassContent(className, methodText);
            XfsGptRequest xfsGptRequest = XfsGptRequest.builder()
                    .max_tokens(Math.max(StrUtil.length(simpleClassContent) * 2, 4096))
                    .message(
                            XfsGptMessage.builder()
                                    .content(simpleClassContent)
                                    .build()
                    ).build();

            resultText = getTestCodeFromApi(xfsGptRequest);
            if (StrUtil.isNotBlank(resultText)) {
                System.out.println("GPT接口返回:\n" + resultText);
                XfsGptResponse xfsGptResponse = JSONUtil.toBean(resultText, XfsGptResponse.class);
                if (xfsGptResponse != null && CollUtil.isNotEmpty(xfsGptResponse.getChoices())) {
                    testCode = xfsGptResponse.getChoices().get(0).getMessage().getContent();
                    if (StrUtil.isNotBlank(testCode)) {
                        testCode = testCode.replaceAll("\\n", "\n");
                    }
                }
            }
        } finally {
            TEST_CODE_GENERATING.set(false);
        }

        return new Tuple2<>(testCode, resultText);
    }

    /**
     * 从api获取测试代码，如果失败则重试一次
     *
     * @param xfsGptRequest 请求参数
     * @return 测试代码
     */
    private String getTestCodeFromApi(XfsGptRequest xfsGptRequest) {
        String resultText;
        String url = getApiUrl();
        HttpResponse response = null;
        try {
            response = getHttpResponse(xfsGptRequest, url);
        } catch (Exception e) {
            if (e instanceof IllegalStateException && StrUtil.contains(e.getMessage(), "XFS ChatGpt接口请求失败")) {
                // 重试一次
                response = getHttpResponse(xfsGptRequest, url);
            } else {
                throw e;
            }
        }
        resultText = response.body();
        return resultText;
    }

    @NotNull
    private HttpResponse getHttpResponse(XfsGptRequest xfsGptRequest, String url) {
        HttpResponse response = HttpUtil.createPost(url)
                .header("Content-Type", "application/json")
                .header("Connection", "keep-alive")
                .header("sercetkey", apiKey)
                .body(JSONUtil.toJsonStr(xfsGptRequest))
                // 60秒超时
                .timeout(60000)
                .execute();
        if (!response.isOk() || StrUtil.isBlank(response.body())) {
            throw new IllegalStateException(
                    "XFS ChatGpt接口请求失败：" + response.getStatus() + " " + response.body());
        }
        return response;
    }
}
